﻿using System;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public enum ScreenState
{
    TransitionOn,
    Active,
    TransitionOff,
    Hidden,
}

public abstract class GameScreen
{
    bool isPopup = false;
    public bool IsPopup
    {
        get { return isPopup; }
        protected set { isPopup = value; }
    }

    TimeSpan transitionOnTime = TimeSpan.Zero;
    public TimeSpan TransitionOnTime
    {
        get { return transitionOnTime; }
        protected set { transitionOnTime = value; }
    }

    TimeSpan transitionOffTime = TimeSpan.Zero;
    public TimeSpan TransitionOffTime
    {
        get { return transitionOffTime; }
        protected set { transitionOffTime = value; }
    }

    float transitionPosition = 1;
    public float TransitionPosition
    {
        get { return transitionPosition; }
        protected set { transitionPosition = value; }
    }

    public byte TransitionAlpha
    {
        get { return (byte)(255 - TransitionPosition * 255); }
    }

    ScreenState screenState = ScreenState.TransitionOn;
    public ScreenState ScreenState
    {
        get { return screenState; }
        protected set { screenState = value; }
    }

    bool isExiting = false;
    public bool IsExiting
    {
        get { return isExiting; }
        protected internal set
        {
            bool fireEvent = !isExiting && value;
            isExiting = value;
            if (fireEvent && (Exiting != null))
            {
                Exiting(this, EventArgs.Empty);
            }
        }
    }

    bool otherScreenHasFocus;
    public bool IsActive
    {
        get
        {
            return !otherScreenHasFocus &&
                   (screenState == ScreenState.TransitionOn ||
                    screenState == ScreenState.Active);
        }
    }

    ScreenManager screenManager;
    public ScreenManager ScreenManager
    {
        get { return screenManager; }
        internal set { screenManager = value; }
    }

    public event EventHandler Exiting;

    public virtual void LoadContent() { }

    public virtual void UnloadContent() { }

    public virtual void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                  bool coveredByOtherScreen)
    {
        this.otherScreenHasFocus = otherScreenHasFocus;

        if (IsExiting)
        {
            // If the screen is going away to die, it should transition off.
            screenState = ScreenState.TransitionOff;

            if (!UpdateTransition(gameTime, transitionOffTime, 1))
            {
                // When the transition finishes, remove the screen.
                ScreenManager.RemoveScreen(this);
            }
        }
        else if (coveredByOtherScreen)
        {
            // If the screen is covered by another, it should transition off.
            if (UpdateTransition(gameTime, transitionOffTime, 1))
            {
                // Still busy transitioning.
                screenState = ScreenState.TransitionOff;
            }
            else
            {
                // Transition finished!
                screenState = ScreenState.Hidden;
            }
        }
        else
        {
            // Otherwise the screen should transition on and become active.
            if (UpdateTransition(gameTime, transitionOnTime, -1))
            {
                // Still busy transitioning.
                screenState = ScreenState.TransitionOn;
            }
            else
            {
                // Transition finished!
                screenState = ScreenState.Active;
            }
        }
    }

    bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
    {
        // How much should we move by?
        float transitionDelta;

        if (time == TimeSpan.Zero)
            transitionDelta = 1;
        else
            transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds /
                                      time.TotalMilliseconds);

        // Update the transition position.
        transitionPosition += transitionDelta * direction;

        // Did we reach the end of the transition?
        if ((transitionPosition <= 0) || (transitionPosition >= 1))
        {
            transitionPosition = MathHelper.Clamp(transitionPosition, 0, 1);
            return false;
        }

        // Otherwise we are still busy transitioning.
        return true;
    }

    public virtual void HandleInput() { }

    public virtual void Draw(GameTime gameTime) { }

    public void ExitScreen()
    {
        // flag that it should transition off and then exit.
        IsExiting = true;
        // If the screen has a zero transition time, remove it immediately.
        if (TransitionOffTime == TimeSpan.Zero)
        {
            ScreenManager.RemoveScreen(this);
        }
    }
}

